package com.cq.hd.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.enums.ResponseEnums;
import com.cq.hd.common.enums.biz.ActiveRedPacketStateEnum;
import com.cq.hd.common.enums.biz.ActiveStateEnum;
import com.cq.hd.common.enums.biz.OrderStateEnum;
import com.cq.hd.common.enums.biz.RedPacketTypeEnum;
import com.cq.hd.common.pagination.Page;
import com.cq.hd.common.response.Throw;
import com.cq.hd.member.api.TbBusinessApi;
import com.cq.hd.member.api.vo.BusinessPageVo;
import com.cq.hd.order.api.TbOrderApi;
import com.cq.hd.order.api.dto.OrderDto;
import com.cq.hd.order.api.vo.OrderVo;
import com.cq.hd.product.api.dto.ReceiveRedPacketDto;
import com.cq.hd.product.api.dto.RedPacketStatisticsDto;
import com.cq.hd.product.api.vo.ActiveRedPacketVo;
import com.cq.hd.product.config.LockUtils;
import com.cq.hd.product.mapper.TbActiveMapper;
import com.cq.hd.product.mapper.TbActiveRedPacketBillMapper;
import com.cq.hd.product.po.TbActivePo;
import com.cq.hd.product.po.TbActiveRedPacketBillPo;
import com.cq.hd.product.po.TbActiveRedPacketPo;
import com.cq.hd.product.mapper.TbActiveRedPacketMapper;
import com.cq.hd.product.service.TbActiveRedPacketService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.util.CollectionUtils;

import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 活动红包表 服务实现类
 * </p>
 *
 * @author mYunYu
 * @since 2023-11-23
 */
@Service
public class TbActiveRedPacketServiceImpl extends ServiceImpl<TbActiveRedPacketMapper, TbActiveRedPacketPo> implements TbActiveRedPacketService {

    @Autowired
    private TbActiveMapper activeMapper;

    @Autowired
    private TbActiveRedPacketBillMapper activeRedPacketBillMapper;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private TbBusinessApi businessApi;

    @Autowired
    private TbOrderApi orderApi;

    @Override
    public Boolean receive(ReceiveRedPacketDto receiveRedPacketDto) {
        Long redPacketId = receiveRedPacketDto.getRedPacketId();

        // 对红包id加锁
        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "receiveRedPacket:" + redPacketId);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            TbActiveRedPacketPo tbActiveRedPacketPo = baseMapper.selectById(receiveRedPacketDto.getRedPacketId());
            if (tbActiveRedPacketPo == null || tbActiveRedPacketPo.getDelState() != 0) {
                Throw.isBusinessException("未找到红包数据");
            }

            if (!tbActiveRedPacketPo.getActiveId().equals(receiveRedPacketDto.getActiveId())) {
                Throw.isBusinessException("红包数据错误");
            }

            TbActivePo tbActivePo = activeMapper.selectById(receiveRedPacketDto.getActiveId());
            if (tbActivePo == null || tbActivePo.getDelState() != 0) {
                Throw.isBusinessException("未找到活动数据");
            }

            if (ActiveStateEnum.NO_RELEASE.getValue().equals(tbActivePo.getActiveState())) {
                Throw.isBusinessException(ResponseEnums.ACTIVE_DOWN);
            }

            // 根据活动时间处理已发布的活动状态
            Integer activeState = tbActivePo.getActiveState();
            LocalDateTime startTime = tbActivePo.getStartTime();
            LocalDateTime endTime = tbActivePo.getEndTime();
            LocalDateTime now = LocalDateTime.now();
            if (startTime.compareTo(now) <= 0 && endTime.compareTo(now) > 0) {
                activeState = ActiveStateEnum.IN_PROGRESS.getValue();
            } else if (endTime.compareTo(now) <= 0) {
                activeState = ActiveStateEnum.ENDED.getValue();
            } else if (startTime.compareTo(now) > 0) {
                activeState = ActiveStateEnum.NO_START.getValue();
            }

            if (ActiveStateEnum.ENDED.getValue().equals(activeState)) {
                Throw.isBusinessException("活动已结束");
            }

            if (ActiveStateEnum.NO_START.getValue().equals(activeState)) {
                Throw.isBusinessException("活动未开始");
            }

            // 如果用户已领取该活动的红包，则不能再领取
            Integer receiveCount = activeRedPacketBillMapper.selectCount(new QueryWrapper<TbActiveRedPacketBillPo>().eq("del_state", 0)
                    .eq("active_id", tbActiveRedPacketPo.getActiveId()).eq("user_id", receiveRedPacketDto.getUserId()));
            if (receiveCount != null && receiveCount > 0) {
                Throw.isBusinessException("你已领取过活动红包");
            }

            // 判断是否是该活动商家的新用户,如果不是,提示"仅限新用户领取"
            OrderDto orderDto = new OrderDto();
            orderDto.setBusinessId(tbActiveRedPacketPo.getBusinessId());
            orderDto.setUserId(receiveRedPacketDto.getUserId());
            orderDto.setOrderStates(Arrays.asList(OrderStateEnum.WAIT_PAY.getValue(), OrderStateEnum.WAIT_VERIFY.getValue(),
                    OrderStateEnum.VERIFYING.getValue(), OrderStateEnum.FINISH.getValue(), OrderStateEnum.VERIFIED.getValue(),
                    OrderStateEnum.PAYING.getValue()));
            List<OrderVo> orderVos = orderApi.listByDto(orderDto).unpack();
            if (!CollectionUtils.isEmpty(orderVos)) {
                // 不是商家新用户
                Throw.isBusinessException("仅限新用户领取");
            }

            TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

            try {
                // 扣减红包总数
                int count = baseMapper.subCount(tbActiveRedPacketPo.getId(), 1);
                if (count <= 0) {
                    Throw.isBusinessException("红包已被领完");
                }

                // 添加红包流水
                TbActiveRedPacketBillPo tbActiveRedPacketBillPo = new TbActiveRedPacketBillPo();
                tbActiveRedPacketBillPo.setBusinessId(tbActiveRedPacketPo.getBusinessId());
                tbActiveRedPacketBillPo.setActiveId(receiveRedPacketDto.getActiveId());
                tbActiveRedPacketBillPo.setUserId(receiveRedPacketDto.getUserId());
                tbActiveRedPacketBillPo.setRedPacketId(tbActiveRedPacketPo.getId());
                tbActiveRedPacketBillPo.setAmt(tbActiveRedPacketPo.getAmt());
                tbActiveRedPacketBillPo.setState(ActiveRedPacketStateEnum.NO_USE.getValue());
                tbActiveRedPacketBillPo.setValidDay(tbActiveRedPacketPo.getValidDay());
                tbActiveRedPacketBillPo.setReceiveTime(now);
                tbActiveRedPacketBillPo.setExpireTime(now.plusDays(tbActiveRedPacketPo.getValidDay()));
                tbActiveRedPacketBillPo.setCreateTime(now);
                tbActiveRedPacketBillPo.setRedPacketType(RedPacketTypeEnum.NEW_USER.getValue());
                tbActiveRedPacketBillPo.setTitle(tbActiveRedPacketBillPo.getTitle());
                count = activeRedPacketBillMapper.insert(tbActiveRedPacketBillPo);
                if (count <= 0) {
                    Throw.isBusinessException("领取失败");
                }

                transactionManager.commit(transaction);
            } catch (Exception e) {
                //回滚事务
                transactionManager.rollback(transaction);
                log.error("<领取红包>事务异常回滚", e);
                Throw.isBusinessException(e.getMessage());
            }

            return true;
        } finally {
            LockUtils.unlock(lockKey);
        }
    }

    @Override
    public Page<ActiveRedPacketVo> pageValidRedPacket(RedPacketStatisticsDto redPacketStatisticsDto) {
        Long businessId = redPacketStatisticsDto.getBusinessId();
        if (businessId == null || businessId <= 0) {
            Long userId = redPacketStatisticsDto.getUserId();
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            BusinessPageVo businessPageVo = businessApi.getByUserId(userId).unpack();
            if (businessPageVo == null) {
                // 如果不是商家，则返回空
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            redPacketStatisticsDto.setBusinessId(businessPageVo.getId());
        }

        PageHelper.startPage(redPacketStatisticsDto.getPageNum(), redPacketStatisticsDto.getPageSize());
        List<ActiveRedPacketVo> redPacketVos = baseMapper.listValidRedPacket(redPacketStatisticsDto);
        PageInfo<ActiveRedPacketVo> pageInfo = new PageInfo<>(redPacketVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

}
